package com.school.admin.common.aop;


import com.school.admin.common.annotation.DataAuthority;
import com.school.admin.common.utils.HttpKit;
import com.school.admin.common.utils.UserInfoUtil;
import com.school.admin.entity.MallSysUser;
import com.school.admin.entity.SysOperateLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;

/**
 * @author :sunpx
 * @date :created in 2020/6/24 9:10
 * @desc :日志切面
 */
@Aspect
@Component
@Slf4j
public class LogSection {

    //申明切入点
    @Pointcut(value = "@annotation(com.school.admin.common.annotation.DataAuthority)")
    public void cutService() {
    }



    @Around("cutService()")
    public Object recordSysLog(ProceedingJoinPoint point) throws Throwable {

        //先执行业务
        Object result = point.proceed();

        Signature sig = point.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Object target = point.getTarget();
        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
        String methodName = currentMethod.getName();
        Object[] params = point.getArgs();
        StringBuilder sb = new StringBuilder();

        //获取注解的参数
        DataAuthority annotation = currentMethod.getAnnotation(DataAuthority.class);
        String bussinessName = annotation.name();
        int key = annotation.key();
        if (key==0){
            return result;
        }

        MallSysUser mallSysUser = new MallSysUser();
        for (int i = 0; i < params.length; i++) {

            if (key == 9) {
                mallSysUser = MallSysUser.class.cast(params[i]);
                break;
            }

            sb.append(params[i]);
            sb.append(" & ");
        }

        String res = "";
        String userName = "";
        if (key == 9) {
            res = mallSysUser.getUsername() + "执行了" + bussinessName + "操作:登录";
            userName = mallSysUser.getUsername();
        } else {
            res = UserInfoUtil.getUsername() + "执行了" + bussinessName + "操作" + "参数:" + sb.toString();
            userName = UserInfoUtil.getUsername();
        }


        SysOperateLog sysOperateLog = new SysOperateLog()
                .setCreatetime(new Date())
                .setLogType(key)
                .setLogContent(res)
                .setOperatorName(userName)
                .setOperatorId(UserInfoUtil.getUserId())
                .setIp(HttpKit.getIpAddress());


        //记录日志
        LogThread logThread = new LogThread(sysOperateLog);
        ThreadPoolExecutorTool.getThreadPoolExecutorTool().execute(logThread);
        return result;
    }

    @AfterThrowing(pointcut = "cutService()", throwing = "e")
    public void afterThrowing(JoinPoint point, Throwable e) throws NoSuchMethodException {
        try {
            Signature sig = point.getSignature();
            MethodSignature msig = (MethodSignature) sig;
            Object target = point.getTarget();
            Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
            DataAuthority annotation = currentMethod.getAnnotation(DataAuthority.class);
            String bussinessName = annotation.name();
            Integer key = 8;
            String message = "用户:" + UserInfoUtil.getUsername() + "执行<" + bussinessName + ">操作时,出现" + e.toString() + "异常;具体信息:" + e.getMessage();

            SysOperateLog sysOperateLog = new SysOperateLog()
                    .setCreatetime(new Date())
                    .setLogType(key)
                    .setLogContent(message)
                    .setOperatorName(UserInfoUtil.getUsername())
                    .setOperatorId(UserInfoUtil.getUserId())
                    .setIp(HttpKit.getIpAddress());
            LogThread logThread = new LogThread(sysOperateLog);
            ThreadPoolExecutorTool.getThreadPoolExecutorTool().execute(logThread);
        } catch (Exception er) {
            log.error("日志记录出错!", er);
        }
    }
}
